/*
 * Copyright (c) 2021 wuqingtao
 * generator is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *   http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
 * WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 *
 * Author: wuqingtao (wqt_1101@qq.com)
 * CreateTime: 2021-01-25 23:25:03+0800
 */

// Package generator 生成县级以上行政区划文件
package generator

import (
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"os"
	"regexp"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

// Item 项目
type Item struct {
	Code string  `plist:"code" xml:"code,attr" json:"code"`
	Name string  `plist:"name" xml:"name,attr" json:"name"`
	City []*Item `plist:"city,omitempty" xml:"city,omitempty" json:"city,omitempty"`
	Area []*Item `plist:"area,omitempty" xml:"area,omitempty" json:"area,omitempty"`
}

var reID = regexp.MustCompile(`^\d+$`)

// GetFromURL 从url读取
func GetFromURL(url string) ([]*Item, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	return readHTML(resp.Body)
}

// ReadFromFile 从文件读取
func ReadFromFile(filename string) ([]*Item, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return readHTML(f)
}

var replacer = strings.NewReplacer("\t", "_", " ", "_", " ", "_")

// readHTML 读取html
func readHTML(r io.Reader) (items []*Item, err error) {
	doc, err := goquery.NewDocumentFromReader(r)
	if err != nil {
		return
	}
	items = make([]*Item, 0, 34)
	tds := doc.Find("td")
	var id string
	var first bool
	tds.EachWithBreak(func(i int, s *goquery.Selection) bool {
		text := replacer.Replace(s.Text())
		if strings.HasPrefix(text, "注") {
			return false
		}
		if text == "" {
			return true
		}
		if reID.MatchString(text) {
			id = text
			first = true
			return true
		}
		if !first {
			return true
		}
		items = append(items, &Item{Code: id, Name: strings.TrimSuffix(text, "*")})
		id = ""
		return true
	})
	return
}

// ConverToTree 转换成树
func ConverToTree(items []*Item) []*Item {
	out := make([]*Item, 0, 34)
	var p, c *Item
	for _, item := range items {
		item := item
		index := strings.LastIndexByte(item.Name, '_')
		// 省或者直辖市
		// fmt.Println(item.Name, index)
		if index < 0 {
			p = item
			// 如果是直辖市,将直辖市当作city存储
			if strings.HasSuffix(item.Name, "市") {
				c = &Item{Code: item.Code, Name: item.Name}
				item.City = append(item.City, c)
			}
			out = append(out, p)
			continue
		}
		// 删除前缀"_"
		item.Name = strings.TrimFunc(item.Name, func(r rune) bool {
			return r == '_'
		})
		// 如果前缀"_"少于3个,是地级市
		if index >= 2 {
			// 区或者县
			if item.Code == "" {
				item.Code = fmt.Sprintf("%s__%d", c.Code, len(c.Area)+1)
			}
			c.Area = append(c.Area, item)
			continue
		}
		p.City = append(p.City, item)
		c = item
	}
	return out
}

// Value 行政单位
type Value struct {
	Code string `xml:"code,attr"`
	Name string `xml:"name,attr"`
}

// Province 省直辖市
type Province struct {
	Value
	City []*City `xml:"city,omitempty"`
}

// City 市
type City struct {
	Value
	// 区
	Area []Value `xml:"area,omitempty"`
}

// CN 中国行政区域
type CN struct {
	XMLName xml.Name `xml:"resources"`
	// Value
	Province []*Province `xml:"prov"`
}

// ConverToXMLStruct 转换成xml所需要的结构
func ConverToXMLStruct(items []*Item) *CN {
	cn := &CN{
		// Value: Value{
		// 	Code: "0",
		// 	Name: "中国",
		// },
		Province: make([]*Province, 0, 34),
	}
	for _, province := range items {
		p := &Province{
			Value: Value{
				Code: province.Code,
				Name: province.Name,
			},
		}
		for _, city := range province.City {
			c := &City{
				Value: Value{
					Code: city.Code,
					Name: city.Name,
				},
			}
			for _, area := range city.Area {
				c.Area = append(c.Area, Value{
					Code: area.Code,
					Name: area.Name,
				})
			}
			p.City = append(p.City, c)
		}
		cn.Province = append(cn.Province, p)
	}
	return cn
}
